#ifndef slak_mesh_Mesh_h
#define slak_mesh_Mesh_h

#include <SDL_opengl.h>
#include <list>
#include <map>

namespace slak {
	namespace mesh {
		/* Patch is rendered with a single glDrawElements */
		struct Patch {
			GLenum draw_mode;
			int vertex_count;
			float * vertices,
			      * normals;
			int elem_count;
			unsigned int * indices;

			Patch() : 
				draw_mode(GL_POINTS), 
				vertex_count(0),
				vertices(0), 
				normals(0), 
				elem_count(0),
				indices(0)
			{}
			void render();
		};
		typedef std::list<Patch*> PatchList;

		struct Material;
		typedef std::list<Material*> MaterialList;
		typedef std::map<Material*, PatchList> MaterialMap;

		/* Mesh is a collection of Materials and Patches. Each
		 * material may be used by several Patches. Material may
		 * consist of a number of passes. Hence, to render the mesh 
		 * we need to ask each Material to render its collection of
		 * Patches (and Material will take care of passes).
		 */
		struct Mesh { 
			MaterialList materials;
			MaterialMap mat2patches;

			void append(Material * mat, Patch * patch) 
			{
				if (mat2patches.count(mat) == 0) {
					materials.push_back(mat);
					mat2patches[mat] = PatchList();
				}
				mat2patches[mat].push_back(patch);
			}

			void render();
		};
	}
}

#endif
